﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Runtime.CompilerServices;
using ConnectionControl;
using System.Windows.Forms;
using pokerServer.GameManagment.GameTools;
using pokerServer.ProtHandlers;

namespace ConnectionControl
{
	
	public class ConnectionManag
	{
		public static ConcurrentDictionary<String, ClientConnection> clients = new ConcurrentDictionary<String,ClientConnection>();
		public static ConcurrentBag<ClientConnection> tempClien = new ConcurrentBag<ClientConnection>();		
		Boolean flag = false ,shtingDown = false;
		public TableManage tablem;
		private TextBox ucount,conCount;
		private ListBox ulist;
		delegate void SetUserCallback(String[] text);
		delegate void SetTextCallback(String text);

		public ConnectionManag(TextBox ucount,TextBox conCount, ListBox ulist)
		{
			this.ucount = ucount;
			this.conCount = conCount;
			this.ulist = ulist;
			tablem = new TableManage(this);
			
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void tempAdd(TcpClient tcl)
		{
			if (!shtingDown)
			{
				ClientConnection c = new ClientConnection(this, tcl);
				c.startWork();
				tempClien.Add(c);
				updateConFields(tempClien.Count +"");
				Thread.Sleep(100);
			}
		
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void addPerm(String name, ClientConnection CC)
		{
			if (!shtingDown)
			{
				clients.TryAdd(name, CC);
				tempClien.TryTake(out CC);
				updateFields(clients.Count + "");
				updateUlist(clients.Keys.ToArray());				
			}
			
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public Boolean exists(String name)
		{
			return clients.ContainsKey(name);
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void removeTemp(ClientConnection c)
		{
			try
			{
				tempClien.TryTake(out c);
				updateFields(clients.Count + "");
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void remove(String name)
		{
			if ((name != null) && clients.Keys.Contains(name))
			{

				ClientConnection t;
				if (clients.TryGetValue(name, out t))	
				{					
					sendAll(name + "Has left the server!");
					clients.TryRemove(name, out t);
					updateFields(clients.Count + "");
					updateUlist(clients.Keys.ToArray());
				}
			}
		}
		
		/*
		[MethodImpl(MethodImplOptions.Synchronized)]
		public Boolean joinTable(int id, String name, out TableErrors t)
		{
			if(clients.ContainsKey(name))
				return tablem.joinTable(id, clients[name],out t);
			else
				t = TableErrors.ERR_NoSuchUser;
					return false;
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public Boolean joinSeat(int tid,int sid, String name, out TableErrors t)
		{
			if(clients.ContainsKey(name))
				return tablem.joinSeat(tid, sid, clients[name],out t);
			else
				t = TableErrors.ERR_NoSuchUser;
					return false;
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public Boolean leaveSeat(int tid, int sid, String name, out TableErrors t)
		{
			if (clients.ContainsKey(name))
				return tablem.leaveSeat(tid, sid, clients[name], out t);
			else
				t = TableErrors.ERR_NoSuchUser;
			return false;
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public Boolean leaveTable(int tid,String name, out TableErrors t)
		{
			if (clients.ContainsKey(name))
				return tablem.leaveTable(tid, clients[name], out t);
			else
				t = TableErrors.ERR_NoSuchUser;
					return false;
		}
		*/
		[MethodImpl(MethodImplOptions.Synchronized)]
		public void sendAll(String s)
		{
			foreach (String k in clients.Keys)
			{
				clients[k].SendMsg(s);
			}
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void checkAlive()
		{

			foreach (String k in clients.Keys)
			{
				if (!clients[k].isAlive())
					remove(k);
			}
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void sendPM(String name, String msg)
		{
			if (clients.ContainsKey(name))
			{
				clients[name].SendMsg(msg);
			}
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void shutDown()
		{
			shtingDown = true;
			sendAll("SYSTEM ShutDown MSG");
			foreach (String k in clients.Keys)
			{
				ClientConnection v;
				Console.WriteLine("PermClients :"+clients.TryRemove(k, out v));
				v.stopWorking();
				//remove(k);
			}

			for (int i = 0; i < tempClien.Count; i++)
			{
				ClientConnection v ;
				System.Console.WriteLine("TempCon:"+tempClien.TryTake(out v));
				v.stopWorking();
			}
			tablem.stopTables();
			tablem.shutDown();
			
				flag = true;
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public Boolean isShutdown()
		{
			return flag;
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public void reActivate()
		{
			if (shtingDown)
			{
				shtingDown = false;
				flag = false;
			}
			//tablem = new TableManage(this);
			tablem.startTables();
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public int getNumconnect()
		{			
			return(clients.Count);
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public String[] getUserlist()
		{
			String[] t = new String[clients.Count];
			int i = 0;
			foreach (String k in clients.Keys)
			{
				t[i++] = k;
			}
			return t;
		}
		/*
		[MethodImpl(MethodImplOptions.Synchronized)]
		public String getTables()
		{
			return tablem.getTableList();
		}

		[MethodImpl(MethodImplOptions.Synchronized)]
		public String getPlayers(int tableId)
		{
			return tablem.getPlayerList(tableId);
		}
		*/
		private void updateFields(String num)
		{
			if (this.ucount.InvokeRequired)
			{
				SetTextCallback d = new SetTextCallback(updateFields);
				this.ucount.Invoke(d, new object[] { num });
			}
			else
				this.ucount.Text = num;
			
		}

		private void updateUlist(String[] ulistnames)
		{
			if (this.ulist.InvokeRequired)
			{
				SetUserCallback d = new SetUserCallback(updateUlist);
				this.ulist.Invoke(d, new object[] { ulistnames });
			}
			else
			{
				ulist.Items.Clear();
				ulist.Items.AddRange(ulistnames);
			}
		}

		private void updateConFields(String num)
		{
			if (this.conCount.InvokeRequired)
			{
				SetTextCallback d = new SetTextCallback(updateConFields);
				this.conCount.Invoke(d, new object[] { num });
			}
			else
				this.conCount.Text = num;

		}
	

	}
}
